#!/usr/bin/env python
# -*- coding: utf-8 -*-

import sys, getpass, logging
from logging import error, warning, info, debug
from xmpp import JID, Client, Message
import time, math

def mean(samples):
    if len(samples) == 0: return 0
    return float(sum(samples)) / len(samples)
    
def stddev(samples):
    if len(samples) <= 1: return 0
    m = mean(samples)
    sum = reduce(lambda sum, x: sum + (x - m) ** 2, samples, 0)
    return math.sqrt(float(sum) / (len(samples) - 1))

class IncrementingBot:
    SAMPLE_SIZE = 10
    
    def __init__(self, client, *args):
        self.log = logging.getLogger(self.__class__.__name__)
        self.log.setLevel(logging.INFO)
        self.client = client
        self.client.RegisterHandler("message", self.messageReceived)        
        if len(args) >= 2:
            self.client.send(Message(args[0], args[1]))
        self.samples = []
        self.t = 0
        
    def messageReceived(self, client, stanza):
        self.log.debug("message stanza received: %s" % unicode(stanza))
        try:
            val = stanza.getBody()
            if val is None: return            
            if self.t:
                t = time.clock()
                self.samples.append(t - self.t)
                self.t = t
            else:
                self.t = time.clock()
            self.client.send(Message(stanza.getFrom(), u"%d" % (int(val) + 1)))
            self.log.debug("len(self.samples): %d" % len(self.samples))
            if len(self.samples) % self.SAMPLE_SIZE == 0 and len(self.samples) > 0:
                self.log.info("vol: %d, mean: %.3f secs, stddev: %.3f" % (len(self.samples), mean(self.samples), stddev(self.samples)))
                self.samples = []
        except ValueError: pass

class ChatStates:
    def __init__(self, client):
        self.client = client
        self.client.RegisterHandler("message", self.chatStateReceived, ns="http://jabber.org/protocol/chatstates")

    def chatStateReceived(self, client, stanza):
        debug("chatstate stanza received: %s" % unicode(stanza))
        if stanza.getTag("active"):
            msg = "ты активен"
        elif stanza.getTag("composing"):
            msg = "ты пишешь"
        elif stanza.getTag("paused"):
            msg = "ты не пишешь"
        elif stanza.getTag("inactive"):
            msg = "ты не активен"
        elif stanza.getTag("gone"):
            msg = "ты ушёл"
        else:
            msg = "неизвестная мне строфа: %s" % unicode(stanza)
        self.client.send(Message(stanza.getFrom(), msg))

class JabberEvent:
    def __init__(self, client):
        self.client = client
        self.client.RegisterHandler("message", self.eventReceived, ns="jabber:x:event")

    def eventReceived(self, client, stanza):
        debug("event stanza received: %s" % unicode(stanza))
        x = stanza.getTag("x")
        if x.getTag("composing"):
            msg = "ты пишешь"
        else:
            msg = "ты не пишешь"
        self.client.send(Message(stanza.getFrom(), msg))
        
if __name__ == "__main__":
    logging.basicConfig(level=logging.DEBUG)
    
    if len(sys.argv) < 3:
        error("Usage: chatstatesbot.py jid bot-class")
        sys.exit(1)
        
    botClass = sys.argv[2]
    if not botClass in vars().keys():
        error("Bot class %s not found" % botClass)
        sys.exit(1)
    
    jid = JID(sys.argv[1])
    password = getpass.getpass()
    
    c = Client(jid.getDomain(), debug=[])
    res = c.connect()
    
    if not res:
        error("Unable to connect to server %s" % jid.getDomain())
        sys.exit(1)
    elif res <> "tls":
        warning("Unable to establish secure TLS connection")
    
    c.auth(jid.getNode(), password, jid.getResource())
    vars()[botClass](c, *sys.argv[3:])
    c.sendInitPresence()
    
    info("Bot started")
    
    while True:
        c.Process(1)

